package cn.ryh.pay.config;

import cn.ryh.pay.config.properties.PayWxProperties;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;

/**
 * @author Raoyh
 * @Description
 * @create 2023-02-15 18:29
 */
@Configuration
public class PayWxConfig {
    @Resource
    private PayWxProperties payWxProperties;

    /**
     * 获取商户私钥文件
     *
     * @return
     */
    private PrivateKey getPrivateKey() {
        try {
            ClassPathResource classPathResource = new ClassPathResource(payWxProperties.getPrivateKeyPath());
            return PemUtil.loadPrivateKey(classPathResource.getInputStream());
        } catch (IOException e) {
            throw new RuntimeException("商户私钥不存在");
        }
    }

    /**
     * 获取签名验证器
     *
     * @throws IOException
     * @throws GeneralSecurityException
     * @throws HttpCodeException
     * @throws NotFoundException
     */
    @Bean
    public Verifier getVerifier() throws GeneralSecurityException, IOException, HttpCodeException, NotFoundException {
        // 获取商户私钥
        PrivateKey privateKey = this.getPrivateKey();
        // 私钥签名对象
        PrivateKeySigner privateKeySigner = new PrivateKeySigner(payWxProperties.getMchSerialNo(), privateKey);
        // 身份认证对象
        WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(payWxProperties.getMchId(), privateKeySigner);
        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        // 向证书管理器增加需要自动更新平台证书的商户信息
        certificatesManager.putMerchant(payWxProperties.getMchId(), wechatPay2Credentials,
                payWxProperties.getApiV3Key().getBytes(StandardCharsets.UTF_8));
        // ... 若有多个商户号，可继续调用putMerchant添加商户信息
        // 从证书管理器中获取verifier
        return certificatesManager.getVerifier(payWxProperties.getMchId());
    }

    /**
     * 获取Http请求对象
     * 后面跟使用Apache HttpClient一样
     *
     * @return
     */
    @Bean
    public CloseableHttpClient getWxPayClient(Verifier verifier) {
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(payWxProperties.getMchId(), payWxProperties.getMchSerialNo(), this.getPrivateKey())
                .withValidator(new WechatPay2Validator(verifier));
        // ... 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient

        // 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签，并进行证书自动更新
        return builder.build();
    }
}
